package com.dkts.oil.test;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

public class GeoJsonExporter {

    public static void main(String[] args) {
        String inputCsvPath = args.length > 0 ? args[0] :
                "C:\\Users\\heyou\\Desktop\\AIS数据.csv";
        String outputDirPath = args.length > 1 ? args[1] : "output_geojson";

        File outputDir = new File(outputDirPath);
        if (!outputDir.exists()) {
            outputDir.mkdirs();
        }

        try (Reader reader = new FileReader(inputCsvPath, StandardCharsets.UTF_8)) {
            CSVParser parser = CSVFormat.DEFAULT.withFirstRecordAsHeader().parse(reader);

            Map<String, List<CSVRecord>> mmsiMap = new HashMap<>();
            for (CSVRecord record : parser) {
                String mmsi = record.get("mmsi");
                mmsiMap.computeIfAbsent(mmsi, k -> new ArrayList<>()).add(record);
            }

            ObjectMapper mapper = new ObjectMapper();

            for (Map.Entry<String, List<CSVRecord>> entry : mmsiMap.entrySet()) {
                String mmsi = entry.getKey();
                List<CSVRecord> records = entry.getValue();
                if (records.size() < 2) continue;

                records.sort(Comparator.comparing(r -> r.get("time")));

                ObjectNode featureCollection = mapper.createObjectNode();
                featureCollection.put("type", "FeatureCollection");
                ArrayNode features = mapper.createArrayNode();

                ObjectNode feature = mapper.createObjectNode();
                feature.put("type", "Feature");

                // 几何部分
                ObjectNode geometry = mapper.createObjectNode();
                geometry.put("type", "LineString");
                ArrayNode coordinates = mapper.createArrayNode();

                Set<String> timeSet = new HashSet<>(); // 用于按时间去重
                for (CSVRecord record : records) {
                    String time = record.get("time");
                    if (!timeSet.add(time)) {
                        // 时间重复，跳过该点
                        System.out.println(record);
                        continue;
                    }
                    try {
                        ArrayNode coord = mapper.createArrayNode();
                        coord.add(Double.parseDouble(record.get("lon")));
                        coord.add(Double.parseDouble(record.get("lat")));
                        coordinates.add(coord);
                    } catch (NumberFormatException e) {
                        System.err.println("跳过无效坐标：" + record.get("lon") + "," + record.get("lat"));
                    }
                }
                geometry.set("coordinates", coordinates);
                feature.set("geometry", geometry);

                // 属性部分
                ObjectNode properties = mapper.createObjectNode();
                CSVRecord first = records.get(0);
                putSafe(properties, "mmsi", first);
                putSafe(properties, "imo", first);
                putSafe(properties, "nationality", first);
                putSafe(properties, "name", first);
                putSafe(properties, "callsign", first);
                putSafe(properties, "length", first);
                putSafe(properties, "width", first);
                putSafe(properties, "left", first);
                putSafe(properties, "tail", first);
                putSafe(properties, "draught", first);
                putSafe(properties, "dest", first);
                putSafe(properties, "eta", first);
                putSafe(properties, "shiptype", first);
                putSafe(properties, "eta_std", first);

                // 这里start_time和end_time可能需要用去重后的时间点，我这里保持原有逻辑
                properties.put("start_time", records.get(0).get("time"));
                properties.put("end_time", records.get(records.size() - 1).get("time"));

                // 轨迹点数组
                ArrayNode trackPoints = mapper.createArrayNode();

                // 再次做时间去重，防止重复点出现在轨迹属性中
                Set<String> trackTimeSet = new HashSet<>();
                for (CSVRecord record : records) {
                    String time = record.get("time");
                    if (!trackTimeSet.add(time)) {
                        continue;
                    }
                    ObjectNode point = mapper.createObjectNode();
                    try {
                        point.put("lon", Double.parseDouble(record.get("lon")));
                        point.put("lat", Double.parseDouble(record.get("lat")));
                    } catch (NumberFormatException e) {
                        continue;
                    }
                    putSafe(point, "time", record);
                    putSafe(point, "speed", record);
                    putSafe(point, "cog", record);
                    putSafe(point, "hdg", record);
                    putSafe(point, "rot", record);
                    putSafe(point, "navistat", record);
                    trackPoints.add(point);
                }
//                properties.set("track_points", trackPoints);

                feature.set("properties", properties);
                features.add(feature);
                featureCollection.set("features", features);

                // 输出为 mmsi_xxx.geojson
                File outputFile = new File(outputDir, "mmsi_" + mmsi + ".geojson");
                try (FileWriter writer = new FileWriter(outputFile)) {
                    mapper.writerWithDefaultPrettyPrinter().writeValue(writer, featureCollection);
                    System.out.println("已生成：" + outputFile.getAbsolutePath());
                }
            }

        } catch (Exception e) {
            System.err.println("处理错误：" + e.getMessage());
            e.printStackTrace();
        }
    }

    private static void putSafe(ObjectNode node, String key, CSVRecord record) {
        String value = record.get(key);
        if (value != null && !value.trim().isEmpty()) {
            node.put(key, value);
        }
    }
}
